/*
 * Do List
 * - Redraw icons
 * - Far left column being cut off
 * - Load svn w/o cmts
 * - Embed svn version number in the gadget title
 * - Add sunrise sunset
 * - Wind value negative
 * - Assess current time, do not show old icons
 * 		... at 10am not showing 10-13 timeperiod
 * - temperature variance off
 */
	
/*****************************************************************
 * Globals
 */
/*
 * Array indexed by timePeriod [DDHH], 0219
 * Contains records with the following values:
 * timePeriod, date, hour, daylight, goNoGo, temperature, rain, wind
 */
var ww = new Hash();
var look = new ArrayOfArrays();
var prefs = new _IG_Prefs();
//		var prefs = new _IG_Prefs(__MODULE_ID__);
var keyArr = [];
var hoursArr = [];	// contains only daylight hours, 07, 10, 13, 16
var daysArr = [];	// contains the days of the month, 11, 12, 13,
var datesArr = [];	// contains the MM-DD, unique
var snapArr = [];	// contains the weather for the timeperiod to show
var numDaysDisplayed = 5;	// number of days to display to user
var red = _IG_GetCachedUrl(
	"http://mamcode.googlecode.com/svn/trunk/wwGadget/icons/red1.png" );
var yellow = _IG_GetCachedUrl(
	"http://mamcode.googlecode.com/svn/trunk/wwGadget/icons/yellow1.png" );
var green = _IG_GetCachedUrl(
	"http://mamcode.googlecode.com/svn/trunk/wwGadget/icons/green1.png" );
var blank = _IG_GetCachedUrl(
	"http://mamcode.googlecode.com/svn/trunk/wwGadget/icons/blank.png" );
var goNoGoType = { None:0, Green:1, Yellow:2, Red:3 };


document.body.style.fontFamily = 'lucida grande,arial,helvetica,sans-serif';
document.body.style.fontSize = '11px';
document.body.style.color = 'grey';		//'#D1D3D4';
document.body.style.padding = '3px';
document.body.style.textAlign = 'center';

var content_div = document.createElement('content_div');
content_div.innerHTML = '<div id="content_div" style="font-size:-1; '
	+ 'color:orange; padding:5px; text-align:left;"></div>';
document.body.appendChild(content_div);


/***********************************************************************
 * multidimensional array functions
 */
	function ArrayOfArrays() {
		/* init the outer array */
		this.rowArr = new Array();
		this.length = 0;
	  }	  
	
	ArrayOfArrays.prototype.put = function( rowArray ) {
		/* put array in rows in aoa */
		var row = this.length - 1;
		if ( typeof( this.rowArr[row] ) == 'undefined' ) {
			this.length ++;
			this.rowArr[row] = new Array();
		}
		if( !(typeof(rowArray) === 'undefined') ) this.rowArr[row] = rowArray;
//debug(['AoAput',rowArray.toString(),this.rowArr[row].toString()].join(', '));
	};
	  
	
	ArrayOfArrays.prototype.putItem = function( row, col, value ) {
		/* put items in aoa */
		if ( typeof( this.rowArr[row] ) == 'undefined' ) {
			this.length ++;
			this.rowArr[row] = new Array();
		}
		if( !(typeof(value) === 'undefined') ) this.rowArr[row][col] = value;
//debug(['AoA putItem', row, col, value].join(', '));
	};
	
	
	ArrayOfArrays.prototype.numCols = function() {
		/* get the number of columns in the table */
		var maxCols = parseInt(0);
		for( var row in this.rowArr ){
			var colLen = parseInt(this.rowArr[row].length);
			maxCols = (colLen > maxCols) ? colLen : maxCols;
		}
//		debug("maxCols (" + maxCols + ") ");
		return maxCols;
	  };
	
	
	ArrayOfArrays.prototype.numRows = function() {
		/* get the number of rows in the table */
		return this.length;
//		debug("numRows (" + this.rowArr.length + ") ");
	  };
	
	
	ArrayOfArrays.prototype.get = function(row, col) {
		/* get cell contents */
//debug(['AoA get', row, col, this.rowArr[row][col]].join(', '));
//debug(['AoA has', row, typeof(this.has(row)), this.has(row)].join(', '));
		if( this.has(row) ) return this.rowArr[row][col];
	  };
	

	ArrayOfArrays.prototype.remove = function(row) {
		/* remove a row from the aoa */
//		debug("removing (" + row + "): " + typeof( this.rowArr[row] ) );
		if( this.has(row) ) {
			this.length --;
			delete this.rowArr[row][col];
		}
	};
	

	ArrayOfArrays.prototype.has = function(row) {
		/* check for cell existence */
		return ( typeof( this.rowArr[row] ) != 'undefined' );
	};
	
	
	ArrayOfArrays.prototype.view = function() {
		/* view the aoa */
		debug( 'AoA view' + this.toString() );
	};
	
	
	ArrayOfArrays.prototype.toString = function() {
		/* stringify the aoa */
		var str = "";
		for( var i=0; i<this.rowArr.length; i++ )
			for( var j=0; j<this.rowArr[i].length; j++ )
				str += this.rowArr[i][j] + ', ';
		return str.replace(/, $/,"");
	};
	
	
	ArrayOfArrays.prototype.toArray = function() {
		/* copy the aoa to a single array */
		var oneArr = new Array();
		for( var i=0; i<this.rowArr.length; i++ )
			for( var j=0; j<this.rowArr[i].length; j++ )
				oneArr.push(this.rowArr[i][j]);
		return oneArr;
	};
		
	
/*****************************************************************
 * Presentation
 */	
 
	function getPrettyHours(hours){
		// data in (ints): 07, 10, 13, 16
		// data out:  7 a.m. - 10 a.m., 10 a.m. -  1 p.m.,
		//            1 p.m. -  4 p.m.,  4 p.m. -  7 p.m.
		var hArr = new Array();
		hArr.push( parseInt(hours) );		// start time
		hArr.push( parseInt(hours) + 3 );	// end time
		var pretty = new Array;
		for( var i=0; i<hArr.length; i++ ){
			if( hArr[i] < 12 ) pretty.push(hArr[i] + ' a.m.');
			else pretty.push(hArr[i]-12 + ' p.m.');
		}
		return pretty.join(' - ');
	}
 		
 	
	function mungeArray(){
		/*
		 * 				date1	date2	date3	date4	date5
		 *	period1		gng		gng		gng		gng		gng
		 * 	period2		gng		gng		gng		gng		gng
		 * 	period3		gng		gng		gng		gng		gng
		 * 	period4 	gng		gng		gng		gng		gng
		 * 
		 */
		var snapIndex = 0;
		look.putItem(0, 0, "");
		for (var z = 0; ((z<datesArr.length) && (z<numDaysDisplayed)) ; z++) {
			/* load dates across the top of the array */
			look.putItem(0, parseInt(z)+1, datesArr[z]) || snapIndex++;
		}
		for (var idx=0; (idx<hoursArr.length); idx++) {
			var hours = hoursArr[idx];
			rowNum = look.length;
			var ph = getPrettyHours(hours);
			look.putItem(rowNum, 0, ph) || snapIndex++;
			for (var k=0; ((k<daysArr.length) && (k<numDaysDisplayed)) ; k++) {
				var timePeriod = daysArr[k] + hours;
				var maxGoNoGo = ww.getItem( timePeriod, 'maxGoNoGo');
				if( maxGoNoGo == goNoGoType.Green ){
					theGoNoGo = "<img src='" + green + "'/>";
				} else if( maxGoNoGo == goNoGoType.Red ) {
					theGoNoGo = "<img src='" + red + "'/>";
				} else if( maxGoNoGo == goNoGoType.Yellow ) {
					theGoNoGo = "<img src='" + yellow + "'/>";
				} else if(( maxGoNoGo == goNoGoType.None )
							|| ( typeof(theGoNoGo) == 'undefined') 
							|| ( typeof(maxGoNoGo) == 'undefined') ){
					theGoNoGo = "<img src='" + blank + "'/>";
				}
				var col = parseInt(k) + 1;
				look.putItem(rowNum, col, theGoNoGo) || snapIndex++;
				buildSnap(snapIndex, timePeriod);
			}
		}
	look.view();
	}	
	
	function whatColor(theGoNoGo){
		/* determines what color to label the text */
		var redDiv = "<DIV STYLE='color: red;'>";
		var yellowDiv = "<DIV STYLE='color: gold;'>";
		var greenDiv = "<DIV STYLE='color: green;'>";
		if( theGoNoGo == goNoGoType.Red ) var div = redDiv;
		if( theGoNoGo == goNoGoType.Yellow ) var div = yellowDiv;
		if( theGoNoGo == goNoGoType.Green ) var div = greenDiv;
		return div;
	}
 		
	function buildSnap(atIndex, forTimePeriod){
		var snap = "";
		var snapLabel = new Object;
		snapLabel['temperature'] = 'Temperature (' + prefs.getString('templo')
			+ ' - ' + prefs.getString('temphi') + '): ';
		snapLabel['rain'] = 'Chance of Rain (' + prefs.getString('rain') + '): ';
		snapLabel['wind'] = 'Wind Speed (' + prefs.getString('wind') + '): ';
		if( typeof(ww.getItem( forTimePeriod, 'date')) != 'undefined' ){
			snap += "Date: " + ww.getItem( forTimePeriod, 'date') + '</br>';
			snap += "Time Period: "
					+ getPrettyHours( ww.getItem( forTimePeriod, 'hour'))
					+ '</br>';
			for(var what in snapLabel){
				var div = whatColor(ww.getItem( forTimePeriod, what+'GoNoGo'));
				snap += div + snapLabel[what] + ww.getItem( forTimePeriod, what)
						+ '<div/';
			}
		}
//debug( 'snap: ' + snap );
		if( snap.length != 0 )
			snapArr[atIndex] = '<div style="font-family:Arial; font-size:11px;'
				+ 'background-color:#FFFFDF; border:3pt black; margin:4pt;'
				+ 'padding:4pt; width:130px; height:70px; position:absolute;'
				+ 'top:-10; right:-50;text-align:left;">' + snap + '</div>';
//debug( 'snapArr[atIndex]: ' + snapArr[atIndex] );
	}


	function displayGadget(){
		var backend = new Object();
		backend.data = look.toArray();
		backend._IGG_getNormalView = function(index) {
			/* Required. Returns default HTML of the cell at index to
			 * be displayed when the user is not dragging. */
  			return this.data[index];
		}
	    backend._IGG_isDragSource = function(index) {
	    	/* Required. Returns true if element at index is a drag source */
	    	if( typeof(snapArr[index]) == 'undefined' ){
	    		return false;
	    	} else {	/* check if a valid, displayable cell */
				return true;  // showSnap(index);
	    	}
		}
	    backend._IGG_isDragTarget = function(index, sourceIndex) {
			/* Required. Returns true if element at index is a drag target */
			return false;
		}
	    backend._IGG_handleClick = function(source) {
 		    /* Clicking on a cell displays the snap. */
	      	this._IGG_refreshCell(source);
	    }
    	backend._IGG_getSurrogateView = function(index) {
    		/* Returns the HTML to be displayed under the cursor during a drag. */
			return snapArr[index];
    	}
		backend._IGG_handleDrag = function(source, target) {
			this._IGG_refreshCell(source);
			this._IGG_refreshCell(target);
		}
		var wwGrid = new _IG_Grid(
							backend, "wwgrid", look.numRows(), look.numCols() );
		wwGrid.getTable().border = 1; 
		wwGrid.getTable().cellPadding = 2;
		_gel("content_div").appendChild(wwGrid.getTable()); 
		wwGrid.initDragging();
		
		var content_div2 = document.createElement('content_div');
		content_div2.innerHTML = '<div id="content_div" style="font-size:11px; '
				+ 'color:grey; padding:5px; text-align:center;">'
				+ 'Click on a cell for more information.</div>';
		document.body.appendChild(content_div2);
	}
		
	
/*****************************************************************
 * Process Feed
 */			 
	function assessDaylight(hour){
		h = parseInt(hour);
		if( (h>=7) && (h<19) ){
			hoursArr.push(hour);
			return true;
		}
		return false;
	}
		

	function getGoNoGo(value, pref){
		var v = parseInt(value);
		var p = parseInt(prefs.getString(pref));
		var theGoNoGo = goNoGoType.None;
		var varianceValue = p + (p * (prefs.getString("variance")/100));
		if( v <= p ) theGoNoGo = goNoGoType.Green;
		else if( v <= varianceValue ) theGoNoGo = goNoGoType.Yellow;
		else if( v > varianceValue ) theGoNoGo = goNoGoType.Red;
//debug( ['getGoNoGo', value, pref, varianceValue, theGoNoGo].join(', '));
		return theGoNoGo;
	}
	
	
	function getGoNoGoRange(value, prefLo, prefHi){
		v = parseInt(value);
		pL = parseInt(prefs.getString(prefLo));
		pH = parseInt(prefs.getString(prefHi));
		var theGoNoGo = goNoGoType.None;
		var varianceValueL = pL - (pL * (prefs.getString("variance")/100));
		var varianceValueH = pH + (pH * (prefs.getString("variance")/100));
		if( (v>=pL) && (v<=pH) ) theGoNoGo = goNoGoType.Green;
		else if( (v>=varianceValueL) && (v<=varianceValueH) )
			theGoNoGo = goNoGoType.Yellow;
		else if( (v<varianceValueL) || (v>varianceValueH) )
			theGoNoGo = goNoGoType.Red;
//debug( ['getGoNoGoRange: ', value, varianceValueL, pL,
// pH, varianceValueH, theGoNoGo].join(', '));
		return theGoNoGo;
	}
	
		
	function chipTimePeriod(timePeriod){
		//- A timePeriod is '2007-11-30T19:00:00-05:00'
		//- A chipped timePeriod, a dateHour is '0207', date_hour
		var dateHour = timePeriod.match(/(\w+):+/);
		dateHour = dateHour[1].replace(/T/, '');
		var date = timePeriod.match(/-(\d\d-\d\d)T/);
		var hour = timePeriod.match(/T(\d\d):/);
		var day = timePeriod.match(/-(\d\d)T/);
		daysArr.push( day[1] );
		datesArr.push( date[1] );
		return [dateHour, date[1], hour[1]];
	}


	function getTime(timeObj) {
		var timeKey = 
			timeObj.getElementsByTagName("layout-key")[0].firstChild.nodeValue;
		var itemList = timeObj.getElementsByTagName("start-valid-time");
		for (var i = 0; i < itemList.length ; i++) {
			var [dateHour, date, hour] 
				= chipTimePeriod(itemList[i].firstChild.nodeValue);
//			var dateHour, date, hour 
// 				= chipTimePeriod(itemList[i].firstChild.nodeValue);
			keyArr[i + timeKey] = dateHour;
			ww.putItem(dateHour, "date", date);
			ww.putItem(dateHour, "hour", hour);
			ww.putItem(dateHour, "daylight", assessDaylight(hour));
			ww.putItem(dateHour, "goNoGo", goNoGoType.None);
		}
	}
		
		
	function getArrayKey( index, timeKey ){
		return keyArr[index + timeKey];	//- get secondary key
	}
	
	
	function getTemp(tempObj) {
		var timeKey = tempObj[0].getAttribute("time-layout");
		var itemList = tempObj[0].getElementsByTagName("value");
		for (var i = 0; i < itemList.length ; i++) {
			var dateHour = getArrayKey(i, timeKey);
			var temp = itemList[i].firstChild.nodeValue;
			ww.putItem( dateHour, "temperature", temp);
			ww.putItem( dateHour, "temperatureGoNoGo",
					getGoNoGoRange( temp,'templo', 'temphi' ));
		}
	}
	
	
	function getRain(rainObj) {
		var timeKey = rainObj[0].getAttribute("time-layout");
		var itemList = rainObj[0].getElementsByTagName("value");
		for (var i = 0; i < itemList.length ; i++) {
			var keyDate, keyHour = '';
			var dateHour = getArrayKey(i, timeKey);
// possibly needs to be an array
			[dateHour, keyDate, keyHour] = dateHour.match(/(\d\d)(\d\d)/);
//			dateHour, keyDate, keyHour = dateHour.match(/(\d\d)(\d\d)/);
			var kd = keyDate.replace(/^0*/, ''); //- nec for parseInt to work
			var startDateInt = parseInt(kd);
			var startHourInt = parseInt(keyHour);
			for(var n=0; n<=9; n+=3){
				var newHour = startHourInt + n;
				var newDate = startDateInt;
				if( newHour > 24 ){	//- crossing midnight
					newHour = newHour - 24;
					newDate = newDate + 1;
				}
				newHour=(newHour<10)?'0'+newHour:newHour;
				newDate=(newDate<10)?'0'+newDate:newDate;
				dateHour = newDate + '' + newHour;
				var rain = itemList[i].firstChild.nodeValue;
				ww.putItem(dateHour, "rain", rain);
				ww.putItem( dateHour, "rainGoNoGo", getGoNoGo( rain, "rain" ) );
			}
		}
	}
	
		
	function getWind(windObj) {
		var timeKey = windObj[0].getAttribute("time-layout");
		var itemList = windObj[0].getElementsByTagName("value");
		for (var i = 0; i < itemList.length ; i++) {
			var dateHour = getArrayKey(i, timeKey);
			var wind = itemList[i].firstChild.nodeValue;
			ww.putItem(dateHour, "wind", wind);
			ww.putItem( dateHour, "windGoNoGo", getGoNoGo( wind, "wind" ) );
		}
	}

	
/*****************************************************************
 * Initiate Gadget
 */	
	function responseCallback(response) {
		if (	response == null ||
				typeof(response) != "object" ||
				response.firstChild == null
			){
			_gel("content_div").innerHTML
				= "<i>Sorry data feed broken, try back later.</i>";
			return;
		}
		//- getting time elements
		var timeNodes = response.getElementsByTagName("time-layout");
		for (var i = 0; i < timeNodes.length ; i++) {
			getTime(timeNodes[i]);
		}
		getTemp(response.getElementsByTagName("temperature"));
		getRain(response.getElementsByTagName("probability-of-precipitation"));
		getWind(response.getElementsByTagName("wind-speed"));
		
		ww.winnow();
		ww = ww.sort();
		ww.setGoNoGo();
//		ww.view();
		
		hoursArr = makeUnique(hoursArr).sort(numSort);
		datesArr = makeUnique(datesArr);
		daysArr = makeUnique(daysArr);
		mungeArray();
		displayGadget();
//		_gel("content_div").innerHTML = '<div style="font-family:Arial; font-size:11px;'
//			+ 'background-color:#FFFFDF; border:10pt black; margin:4pt;'
//			+ 'padding:4pt; width:150px; height:70px; position:absolute;'
//			+ 'top:-10; right:-50;text-align:left;">Click on the cell for more information.</div>';
	}
		
		
	function weatherFeed() {
		var zipCode = prefs.getString("zipcode");
//		http://www.weather.gov/forecasts/xml/SOAP_server/ndfdXMLclient.php?whichClient=NDFDgenMultiZipCode&zipCodeList=20124&product=time-series&pop12=pop12&wspd=wspd&appt=appt&Submit=Submit
		var url = "http://www.weather.gov/forecasts/xml/SOAP_server";
		url += "/ndfdXMLclient.php?whichClient=NDFDgenMultiZipCode";
		url += "&zipCodeList=" + zipCode;
		url += "&product=time-series&pop12=pop12&wspd=wspd&appt=appt";
		url += "&Submit=Submit";
		debug( url );
//		_IG_FetchXmlContent(url, responseCallback );
		_IG_FetchXmlContent(url, responseCallback, { refreshInterval: 5 } );
	}

	_IG_SetTitle("Weather or Not ... ?");
	_IG_RegisterOnloadHandler(weatherFeed);